#pragma once
#include "Si.h"
#include "Item.h"


class Robot {
protected:
	const TimeStamp* _currentTime;
	TimeStamp		 _usableFrom;

	Robot(const TimeStamp* ct, const std::string& ts="00010101000000") : _currentTime(ct), _usableFrom(ts) {}
public:
	virtual bool Usable() const = 0;
};


class MovR : public Robot {
		  bool		_sleep;
		  bool		_charged;
		  TimeStamp _lastActionAt;
	const Kg		_range;
	const Kg		_capacity;
	const int		_chargeTime;
		  Kg		_transported;
		  Kg		_total;
public:
	MovR(const TimeStamp* current_time, const Kg& range, const Kg& capacity, const int& chargeTime)
		: Robot(current_time), _sleep(false), _charged(true), _range(range), _capacity(capacity),
		_chargeTime(chargeTime), _transported(0), _total(0) {}

	void Sleep() { _sleep = true; }
	void WakeUp(){ _sleep = false; }
	bool Charge(const TimeStamp& endTime);

	virtual bool Usable() const { return !_sleep && (_usableFrom <= *_currentTime) && _charged; }
	bool Charged() const { return _charged; }
	bool IsSleeping() const { return _sleep; }

	const Kg& Capacity() const { return std::min(_capacity, _range - _transported); }
	const Kg& Range() const { return _range; }
	const int& ChargeTime() const { return _chargeTime; }

	const Kg& CurrentRange() const { return _range - _transported; }
	const TimeStamp& UsableFrom() const { return _usableFrom; }
	const Kg& Transported() const { return _transported; }
	Kg Transport(Item& item);

	friend std::ostream& operator<<(std::ostream& o, const MovR& rhs){ o << rhs.Capacity(); return o; }
};

inline bool operator<(const MovR& lhs, const MovR& rhs);
inline bool operator<=(const MovR& lhs, const MovR& rhs){ return !(rhs < lhs); }
inline bool operator>(const MovR& lhs, const MovR& rhs){ return rhs < lhs; }
inline bool operator>=(const MovR& lhs, const MovR& rhs){ return !(lhs < rhs); }
inline bool operator==(const MovR& lhs, const MovR& rhs){ return !(rhs < lhs) && !(lhs < rhs); }
inline bool operator!=(const MovR& lhs, const MovR& rhs){ return rhs < lhs || lhs < rhs; }


class PowR : public Robot {
public:
	PowR(const TimeStamp* current_time) : Robot(current_time) {}
	void Mount(const TimeStamp& endTime);
	
	virtual bool Usable() const { return _usableFrom <= *_currentTime; } // TODO: PowR state
};